home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.5 Complementary Applications 2004 February / SGI IRIX 6.5 Complementary Applications 2004 February.iso / dist / cde.idb / usr / dt / share / examples / dtdnd / file.c.z / file.c
Encoding:
C/C++ Source or Header  |  2003-11-18  |  21.9 KB  |  787 lines

  1. /*
  2.  * file.c
  3.  *
  4.  * Copyright 2000, Silicon Graphics, Inc.
  5.  * ALL RIGHTS RESERVED
  6.  * 
  7.  * UNPUBLISHED -- Rights reserved under the copyright laws of the United
  8.  * States.   Use of a copyright notice is precautionary only and does not
  9.  * imply publication or disclosure.
  10.  *
  11.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
  12.  * Use, duplication or disclosure by the Government is subject to restrictions
  13.  * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
  14.  * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
  15.  * in similar or successor clauses in the FAR, or the DOD or NASA FAR
  16.  * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
  17.  * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
  18.  *
  19.  * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
  20.  * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
  21.  * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
  22.  * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
  23.  * GRAPHICS, INC.
  24.  */
  25. /* $XConsortium: file.c /main/cde1_maint/1 1995/07/17 16:42:36 drk $ */
  26. /*****************************************************************************
  27.  *****************************************************************************
  28.  **
  29.  **   File:         file.c
  30.  **
  31.  **   Description:  File transfer functions for the CDE Drag & Drop Demo.
  32.  **
  33.  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
  34.  **  (c) Copyright 1993, 1994 International Business Machines Corp.
  35.  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  36.  **  (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
  37.  **      Novell, Inc.
  38.  **
  39.  ****************************************************************************
  40.  ************************************<+>*************************************/
  41.  
  42. #include <stdio.h>
  43. #include <unistd.h>
  44. #include <sys/stat.h>
  45. #include <sys/param.h>
  46.  
  47. #include <X11/Intrinsic.h>
  48.  
  49. #include <Xm/Xm.h>
  50. #include <Xm/DrawingA.h>
  51. #include <Xm/Frame.h>
  52. #include <Xm/Protocols.h>
  53.  
  54. #include <Dt/Dt.h>
  55. #include <Dt/Dnd.h>
  56.  
  57. #include "icon.h"
  58. #include "demo.h"
  59. #include "file.h"
  60.  
  61. extern Widget        topLevel;
  62. extern XtAppContext    appContext;
  63.  
  64.  /*************************************************************************
  65.  *
  66.  *       Data Structures & Private Declarations For Appointment Buffers
  67.  *
  68.  **************************************************************************/
  69.  
  70. /*
  71.  * Specification of drag or drop directory
  72.  */
  73.  
  74. typedef enum {
  75.     DragDirectory,
  76.     DropDirectory
  77. } DragOrDrop;
  78.  
  79. /*
  80.  * File names and contents. The contents are the minimal required by the
  81.  * data typing service to correctly type the file via content-based typing.
  82.  * The file names are appropriate to the type of the contents as well. This
  83.  * demo uses content-based typing to get the appropriate icons for these files.
  84.  */
  85.  
  86. #define FILE_NAME_CSH   "runit"
  87. #define FILE_DATA_CSH   "#! /bin/csh"
  88.  
  89. #define FILE_NAME_PS    "map.ps"
  90. #define FILE_DATA_PS    "%!PS-Adobe-2.0"
  91.  
  92. #define FILE_NAME_TEXT  "tasks"
  93. #define FILE_DATA_TEXT  "Nothing"
  94.  
  95. /*
  96.  * Private file function declarations
  97.  */
  98.  
  99. static XtActionProc    fileCheckForDragProc(Widget, XEvent*, String*,
  100.                         Cardinal*);
  101. static void        fileConvertCallback(Widget, XtPointer, XtPointer);
  102. static void         fileCreateDirectory(char*);
  103. static void         fileCreateFile(char*, char*, char*);
  104. static void        fileCreateFiles(Widget);
  105. static void        fileDragStart(Widget, XEvent*, IconInfo*, int);
  106. static char*        fileGetContents(char*);
  107. static char*        fileGetDemoDirectory();
  108. static char*        fileGetDirectoryName(DragOrDrop);
  109. static void         fileRemoveDirectory(char*);
  110. static void        fileShutdown(Widget, XtPointer, XtPointer);
  111.  
  112.  /*************************************************************************
  113.  *
  114.  *       File Name Drag & Drop
  115.  *
  116.  **************************************************************************/
  117.  
  118. /*
  119.  * fileConvertCallback
  120.  *
  121.  * When converting the data, fills in the file structure with the name(s) of
  122.  * the file(s). When converting DELETE, removes the given file(s) and icon(s)
  123.  * from the filesystem and drawing area respectively.
  124.  */
  125. static void
  126. fileConvertCallback(
  127.         Widget          dragContext,
  128.         XtPointer       clientData,
  129.         XtPointer       callData)
  130. {
  131.         DtDndConvertCallbackStruct *convertInfo =
  132.                                         (DtDndConvertCallbackStruct *) callData;
  133.         IconInfo        *iconArray = (IconInfo *) clientData;
  134.     char        filePath[MAXPATHLEN + 1],
  135.             command[MAXPATHLEN + 4];
  136.         int             ii;
  137.     Widget        fileDraw;
  138.  
  139.     if (convertInfo == NULL) {
  140.         return;
  141.     }
  142.  
  143.     /*
  144.      * Verify the protocol and callback reason
  145.      */
  146.  
  147.     if (convertInfo->dragData->protocol != DtDND_FILENAME_TRANSFER ||
  148.         (convertInfo->reason != DtCR_DND_CONVERT_DATA &&
  149.          convertInfo->reason != DtCR_DND_CONVERT_DELETE)) {
  150.         return;
  151.     }
  152.  
  153.         switch (convertInfo->reason) {
  154.         case DtCR_DND_CONVERT_DATA:
  155.  
  156.         /*
  157.           * Supply the file names of the dragged files
  158.          */
  159.  
  160.                 for (ii = 0; ii < convertInfo->dragData->numItems; ii++) {
  161.             sprintf(filePath, "%s/%s",
  162.                 fileGetDirectoryName(DragDirectory),
  163.                 iconArray[ii].name);
  164.                         convertInfo->dragData->data.files[ii] =
  165.                 XtNewString(filePath);
  166.                 }
  167.                 break;
  168.         case DtCR_DND_CONVERT_DELETE:
  169.  
  170.         /*
  171.          * Delete dragged files as second part of a move operation
  172.          */
  173.  
  174.                 fileDraw = XtNameToWidget(topLevel, "*fileDraw");
  175.  
  176.                 for (ii = 0; ii < convertInfo->dragData->numItems; ii++) {
  177.  
  178.             /* Remove file(s) */
  179.  
  180.                         sprintf(filePath, "%s/%s",
  181.                                 fileGetDirectoryName(DragDirectory),
  182.                                 iconArray[ii].name);
  183.                         sprintf(command, "rm %s", filePath);
  184.                         if (system(command) != 0) {
  185.                                 printf("Unable to remove file \"%s\".\n",
  186.                                          filePath);
  187.                         }
  188.  
  189.                     /* Remove icon(s) */
  190.  
  191.                     if (fileDraw != NULL) {
  192.                             IconDelete(fileDraw, &iconArray[ii]);
  193.  
  194.                             XClearWindow(XtDisplayOfObject(fileDraw),
  195.                                     (XtWindow(fileDraw)));
  196.                             XtCallCallbacks(fileDraw, XmNexposeCallback,
  197.                     NULL);
  198.                     }
  199.         }
  200.                 break;
  201.         }
  202. }
  203.  
  204. /*
  205.  * fileDragFinishCallback
  206.  *
  207.  * Free the file names allocated in fileConvertCallback()
  208.  */
  209. void
  210. fileDragFinishCallback(
  211.         Widget          widget,
  212.         XtPointer       clientData,
  213.         XtPointer       callData)
  214. {
  215.     DtDndDragFinishCallbackStruct *dragFinishInfo =
  216.                 (DtDndDragFinishCallbackStruct *)callData;
  217.     DtDndContext    *dragData = dragFinishInfo->dragData;
  218.     int        ii;
  219.  
  220.     for (ii = 0; ii < dragData->numItems; ii++) {
  221.         XtFree(dragData->data.files[ii]);
  222.     }
  223. }
  224.  
  225. /*
  226.  * fileTransferCallback
  227.  *
  228.  * Handles the transfer of a file or appointment to the draw area.
  229.  * Adds the appropriate icon to the list of icons on the draw area.
  230.  */
  231. void
  232. fileTransferCallback(
  233.         Widget          widget,
  234.         XtPointer       clientData,
  235.         XtPointer       callData)
  236. {
  237.         DtDndTransferCallbackStruct *transferInfo =
  238.                                 (DtDndTransferCallbackStruct *) callData;
  239.         IconInfo       *iconList = NULL, *iconPtr;
  240.         char           *filePath, *name, *contents,
  241.             command[2*MAXPATHLEN + 5];
  242.         int             ii;
  243.  
  244.     if (transferInfo == NULL) {
  245.         return;
  246.     }
  247.  
  248.     /*
  249.      * Verify the protocol and callback reasons
  250.      */
  251.  
  252.         if (transferInfo->dropData->protocol != DtDND_FILENAME_TRANSFER ||
  253.         transferInfo->reason != DtCR_DND_TRANSFER_DATA) {
  254.         return;
  255.     }
  256.  
  257.     if (widget != NULL) {
  258.         XtVaGetValues(widget, XmNuserData, &iconList, NULL);
  259.         }
  260.  
  261.     /*
  262.      * Copy the dropped file(s) to the drop directory
  263.      */
  264.  
  265.         for (ii = 0; ii < transferInfo->dropData->numItems; ii++) {
  266.  
  267.         /* Copy the file(s) */
  268.  
  269.             filePath = transferInfo->dropData->data.files[ii];
  270.  
  271.         contents = fileGetContents(filePath);
  272.  
  273.             if ((name = strrchr(filePath,'/')) == NULL) {
  274.                 name = filePath;
  275.             } else {
  276.                 name++;
  277.             }
  278.                 sprintf(command, "cp %s %s", filePath,
  279.                         fileGetDirectoryName(DropDirectory));
  280.                 if (system(command) != 0) {
  281.                         printf("Could not copy file \"%s\" to \"%s\".\n",
  282.                                 filePath, fileGetDirectoryName(DropDirectory));
  283.                         transferInfo->status = DtDND_FAILURE;
  284.                         return;
  285.                 }
  286.  
  287.         /* Create icon(s) for new file(s) at the drop site */
  288.     
  289.             iconPtr = IconNew();
  290.             IconInitialize(widget, iconPtr,
  291.                 transferInfo->x + ii * 10,
  292.                 transferInfo->y + ii * 10,
  293.                 contents, strlen(contents), name, IconByData);
  294.             iconPtr->next = iconList;
  295.         if (iconList != NULL) {
  296.             iconList->prev = iconPtr;
  297.         }
  298.         iconList = iconPtr;
  299.             XtVaSetValues(widget, XmNuserData, iconList, NULL);
  300.         XtFree(contents);
  301.         }
  302. }
  303.  
  304. /*
  305.  * fileDragSetup
  306.  *
  307.  * Prepares the file draw area to be a drag source.
  308.  */
  309. void
  310. fileDragSetup(
  311.         Widget          fileDraw)
  312. {
  313.         char            translations[] = "<Btn2Down>: fileCheckForDragProc()";
  314.         XtTranslations  newTranslations;
  315.         XtActionsRec    actionTable[] = {
  316.                 {"fileCheckForDragProc", (XtActionProc)fileCheckForDragProc},
  317.         };
  318.  
  319.         XtAppAddActions(appContext, actionTable, 1);
  320.         newTranslations = XtParseTranslationTable(translations);
  321.         XtVaSetValues(fileDraw, XmNtranslations, newTranslations, NULL);
  322.  
  323.         XtAddEventHandler(fileDraw, Button1MotionMask, False,
  324.                 (XtEventHandler)demoDragMotionHandler,
  325.                 (XtPointer)DtDND_FILENAME_TRANSFER);
  326.  
  327.     fileCreateFiles(fileDraw);
  328. }
  329.  
  330. /*
  331.  * fileDropSetup
  332.  *
  333.  * Such a function is not needed since the demoDropSetup() in demo.c registers
  334.  * the draw area as a drop site for drops of file names.
  335.  */
  336.  
  337. /*
  338.  * fileDragStart
  339.  *
  340.  * Initiates a file drag. The function fileCheckForDrag() first determines
  341.  * if the pointer is over a file icon before calling this function.
  342.  */
  343. static void
  344. fileDragStart(
  345.         Widget          widget,
  346.         XEvent         *event,
  347.         IconInfo       *iconArray,
  348.         int             numFiles)
  349. {
  350.         static XtCallbackRec convertCBRec[] = { {fileConvertCallback, NULL},
  351.                                                 {NULL, NULL} };
  352.         static XtCallbackRec dragFinishCBRec[] =
  353.                           { {demoDragFinishCallback, NULL},
  354.                             {fileDragFinishCallback, NULL},
  355.                                                 {NULL, NULL} };
  356.         Widget          dragIcon;
  357.         Arg             arg[1];
  358.  
  359.         convertCBRec[0].closure    = (XtPointer) iconArray;
  360.  
  361.     /*
  362.      * Set up drag icon
  363.      */
  364.  
  365.         if (numFiles == 1) {
  366.             if (iconArray[0].dragIcon == NULL) {
  367.                     iconArray[0].dragIcon = DtDndCreateSourceIcon(widget,
  368.                             iconArray[0].bitmap, iconArray[0].mask);
  369.             }
  370.                 dragIcon = iconArray[0].dragIcon;
  371.         } else {
  372.                 dragIcon = NULL; /* Use default multiple provided by library */
  373.         }
  374.  
  375.         XtSetArg(arg[0], DtNsourceIcon, (XtArgVal)dragIcon);
  376.  
  377.     /*
  378.      * Start the drag
  379.      */
  380.  
  381.         if (DtDndDragStart(widget, event, DtDND_FILENAME_TRANSFER, numFiles,
  382.                         XmDROP_COPY | XmDROP_MOVE,
  383.                         convertCBRec, dragFinishCBRec, arg, 1)
  384.             == NULL) {
  385.  
  386.                 printf("DragStart returned NULL.\n");
  387.         }
  388. }
  389.  
  390. /*
  391.  * fileCheckForDragProc
  392.  *
  393.  * Called when button 2 is pressed in the file drag area. Calls
  394.  * fileCheckForDrag() to determine if the button was pressed over a file
  395.  * icon in which case a drag is started.
  396.  */
  397. static XtActionProc
  398. fileCheckForDragProc(
  399.         Widget          widget,
  400.         XEvent        *event,
  401.         String        *params,
  402.         Cardinal    *numParams)
  403. {
  404.     fileCheckForDrag(widget, event, event->xbutton.x, event->xbutton.y);
  405. }
  406.  
  407. /*
  408.  * fileCheckForDrag
  409.  *
  410.  * Determine if the pointer is over a file icon (within the drag threshold)
  411.  * when button 2 is pressed or when button 1 was pressed and the drag
  412.  * threshold has been exceeded.
  413.  */ 
  414. void
  415. fileCheckForDrag(
  416.         Widget          widget,
  417.         XEvent         *event,
  418.     int        initialX,
  419.     int        initialY)
  420. {
  421.         IconInfo       *iconList, *iconPtr, *iconArray;
  422.  
  423.         XtVaGetValues(widget, XmNuserData, &iconList, NULL);
  424.  
  425.         if (iconList == NULL) {
  426.                 printf("Unable to locate icon list.\n");
  427.         }
  428.  
  429.         for (iconPtr = iconList; iconPtr != NULL; iconPtr = iconPtr->next) {
  430.                 if ((initialX > (int)iconPtr->icon.x &&
  431.                      initialX < (int)(iconPtr->icon.x + iconPtr->icon.width)) &&
  432.                     (initialY > (int)iconPtr->icon.y &&
  433.                      initialY < (int)(iconPtr->icon.y + iconPtr->icon.height))){
  434.  
  435.             /*
  436.              * This starts a single file drag. To start a multiple
  437.              * file drag add elements to the icon array here. The
  438.              * convert and transfer callbacks are already written
  439.              * to handle multiple file transfers. 
  440.              */
  441.  
  442.                         iconArray = (IconInfo *)XtCalloc(1,sizeof(IconInfo));
  443.                         iconArray[0] = *iconPtr;
  444.  
  445.                         fileDragStart(widget, event, iconArray, 1);
  446.                 }
  447.         }
  448. }
  449.  
  450.  /*************************************************************************
  451.  *
  452.  *      File Creation, Initialization & Destruction
  453.  *
  454.  *************************************************************************/
  455.  
  456. /*
  457.  * fileCreateDragSource
  458.  *
  459.  * Create draw area with a frame to serve as the drag source for files.
  460.  */
  461. Widget
  462. fileCreateDragSource(
  463.     Widget        parent)
  464. {
  465.     Widget        fileFrame,
  466.             fileDraw;
  467.  
  468.         fileFrame = XtVaCreateManagedWidget("fileFrame",
  469.                 xmFrameWidgetClass, parent,
  470.                 NULL);
  471.  
  472.         fileDraw = XtVaCreateManagedWidget("fileDraw",
  473.                 xmDrawingAreaWidgetClass, fileFrame,
  474.                 NULL);
  475.         XtAddCallback(fileDraw, XmNexposeCallback, demoDrawExposeCallback,NULL);
  476.  
  477.     return fileDraw;
  478. }
  479.  
  480. /*
  481.  * fileCreateDropSite
  482.  *
  483.  * Such a function is not needed since the drop site is the draw area which
  484.  * is created in demoCreateDropSite() in demo.c
  485.  */
  486.  
  487. /*
  488.  * fileCreateDirectory
  489.  *
  490.  * Create the given directory.
  491.  */
  492. static void
  493. fileCreateDirectory(
  494.         char            *directory)
  495. {
  496.         char            command[MAXPATHLEN + 8];
  497.  
  498.         sprintf(command, "mkdir %s", directory);
  499.         if (system(command) != 0) {
  500.                 printf("Unable to create directory \"%s\"\n", directory);
  501.                 exit(1);
  502.         }
  503. }
  504.  
  505. /*
  506.  * fileCreateFile
  507.  *
  508.  * Given a path (partial or absolute), a file name and data create a file
  509.  * containing the given data using the given path.
  510.  */
  511. static void
  512. fileCreateFile(
  513.         char            *filePath,
  514.         char            *fileName,
  515.     char        *fileData)
  516. {
  517.         FILE            *fp;
  518.         char            filePathAndName[MAXPATHLEN];
  519.  
  520.         sprintf(filePathAndName, "%s/%s", filePath, fileName);
  521.  
  522.         if ((fp = fopen(filePathAndName, "w")) == NULL) {
  523.                 printf("Cannot create file \"%s\" in current directory.\n"
  524.                         "Exiting...\n", filePathAndName);
  525.                 exit(1);
  526.         }
  527.         if (fwrite(fileData, strlen(fileData), 1, fp) != 1) {
  528.                 printf("Cannot write file \"%s\" in current directory.\n"
  529.                         "Exiting...\n", filePathAndName);
  530.                 exit(1);
  531.         }
  532.         fclose(fp);
  533. }
  534.  
  535. /*
  536.  * fileCreateFiles
  537.  *
  538.  * Create drag and drop directories and the files to drag.
  539.  */
  540. static void
  541. fileCreateFiles(
  542.     Widget        fileDraw)
  543. {
  544.         IconInfo        *iconList,
  545.                         *iconPtr;
  546.         char            *dragDirectory,
  547.                         *dropDirectory;
  548.         Atom            WM_DELETE_WINDOW;
  549.  
  550.         WM_DELETE_WINDOW = XmInternAtom(XtDisplay(topLevel), "WM_DELETE_WINDOW",
  551.                 False);
  552.         XmAddWMProtocolCallback(topLevel, WM_DELETE_WINDOW, fileShutdown,
  553.                 (XtPointer)NULL);
  554.  
  555.         dragDirectory = fileGetDirectoryName(DragDirectory);
  556.         dropDirectory = fileGetDirectoryName(DropDirectory);
  557.  
  558.         fileRemoveDirectory(dragDirectory);
  559.         fileCreateDirectory(dragDirectory);
  560.  
  561.         fileRemoveDirectory(dropDirectory);
  562.         fileCreateDirectory(dropDirectory);
  563.  
  564.         fileCreateFile(dragDirectory, FILE_NAME_TEXT, FILE_DATA_TEXT);
  565.         fileCreateFile(dragDirectory, FILE_NAME_CSH,  FILE_DATA_CSH);
  566.         fileCreateFile(dragDirectory, FILE_NAME_PS,   FILE_DATA_PS);
  567.  
  568.         iconPtr = IconNew();
  569.         IconInitialize(fileDraw, iconPtr, 40, 25,
  570.         FILE_DATA_TEXT, strlen(FILE_DATA_TEXT),
  571.         FILE_NAME_TEXT, IconByData);
  572.  
  573.         iconList = iconPtr;
  574.         iconPtr = IconNew();
  575.         iconPtr->next = iconList;
  576.         iconList->prev = iconPtr;
  577.  
  578.         IconInitialize(fileDraw, iconPtr, 105, 25,
  579.         FILE_DATA_CSH, strlen(FILE_DATA_CSH),
  580.         FILE_NAME_CSH, IconByData);
  581.  
  582.         iconList = iconPtr;
  583.         iconPtr = IconNew();
  584.         iconPtr->next = iconList;
  585.         iconList->prev = iconPtr;
  586.  
  587.         IconInitialize(fileDraw, iconPtr, 75, 95,
  588.         FILE_DATA_PS, strlen(FILE_DATA_PS),
  589.         FILE_NAME_PS, IconByData);
  590.  
  591.         iconList = iconPtr;
  592.  
  593.         XtVaSetValues(fileDraw, XmNuserData, iconList, NULL);
  594. }
  595.  
  596. /*
  597.  * fileRemoveDirectory
  598.  *
  599.  * Remove the given directory and its contents if the directory exists.
  600.  */
  601. static void
  602. fileRemoveDirectory(
  603.         char            *directory)
  604. {
  605.         struct stat     fileStatus;
  606.         char            command[MAXPATHLEN + 8];
  607.  
  608.         if (stat(directory, &fileStatus) == 0) { /* directory exists */
  609.                 sprintf(command, "rm -rf %s", directory);
  610.                 if (system(command) != 0) {
  611.                         printf("Unable to remove directory \"%s\"\n"
  612.                                 "Please remove this directory by hand "
  613.                                 "and try again.\n", directory);
  614.                         exit(1);
  615.                 }
  616.         }
  617. }
  618.  
  619. /*
  620.  * fileShutdown
  621.  *
  622.  * Remove the temporary file
  623.  */
  624. static void
  625. fileShutdown(
  626.     Widget        widget,
  627.     XtPointer    clientData,
  628.     XtPointer    callData)
  629. {
  630.         fileRemoveDirectory(fileGetDirectoryName(DragDirectory));
  631.         fileRemoveDirectory(fileGetDirectoryName(DropDirectory));
  632. }
  633.  
  634.  /*************************************************************************
  635.  *
  636.  *      File Utility Functions
  637.  *
  638.  *************************************************************************/
  639.  
  640. /*
  641.  * fileGetContents
  642.  *
  643.  * Open the specified file and read the contents into a buffer which is
  644.  * returned.
  645.  */
  646. static char*
  647. fileGetContents(
  648.     char        *filePath)
  649. {
  650.     char        *contents = NULL;
  651.         struct stat     fileStatus;
  652.     FILE        *fp;
  653.  
  654.         if (stat(filePath, &fileStatus) == 0) { /* file exists */
  655.         contents = (char *) XtMalloc(fileStatus.st_size + 1);
  656.             if ((fp = fopen(filePath, "r")) == NULL) {
  657.                     printf("Cannot open file \"%s\" for reading.\n",
  658.                 filePath);
  659.             XtFree(contents);
  660.             contents = NULL;
  661.             } else if (fread(contents, fileStatus.st_size, 1, fp) != 1) {
  662.                     printf("Cannot read file \"%s\".\n", filePath);
  663.             XtFree(contents);
  664.             contents = NULL;
  665.             }
  666.         if (contents != NULL) {
  667.             contents[fileStatus.st_size] = NULL;
  668.         }
  669.             fclose(fp);
  670.     }
  671.     return contents;
  672. }
  673.     
  674. /*
  675.  * fileGetDemoDirectory
  676.  *
  677.  * Return the directory where the demo directories reside.
  678.  */
  679. static char*
  680. fileGetDemoDirectory()
  681. {
  682.         static char     *demoDirectory = NULL;
  683.         char            currentDirectory[MAXPATHLEN];
  684.         int             status;
  685.  
  686.         if (demoDirectory == NULL) {
  687.                 demoDirectory = (char *) getenv("DNDDEMODIR");
  688.                 if (demoDirectory == NULL) {
  689.                         demoDirectory = (char *) getcwd(NULL, MAXPATHLEN);
  690.                         if (demoDirectory == NULL) {
  691.                             sprintf(
  692.                                 "getcwd() could not get current directory.\n"
  693.                                 "\tUsing \".\" instead.\n",
  694.                                 NULL);
  695.                             demoDirectory = ".";
  696.                         } else {
  697.                             /* strip off the /tmp_mnt */
  698.                 if (strncmp(demoDirectory, "/tmp_mnt/", 9) == 0) {
  699.                     demoDirectory += 8;
  700.                 }
  701.                         }
  702.                 }
  703.         }
  704.         return demoDirectory;
  705. }
  706.  
  707. /*
  708.  * fileGetDirectoryName
  709.  *
  710.  * Gets the name of the directory where the files are dragged from or dropped
  711.  * to depending on which is requested.
  712.  */
  713. static char*
  714. fileGetDirectoryName(
  715.         DragOrDrop      dragOrDrop)
  716. {
  717.         static char     *dragDirectory = NULL;
  718.         static char     *dropDirectory = NULL;
  719.  
  720.         switch (dragOrDrop) {
  721.         case DragDirectory:
  722.                 if (dragDirectory == NULL) {
  723.                         dragDirectory = (char *) XtMalloc(MAXPATHLEN + 1);
  724.                         sprintf(dragDirectory, "%s/FileDragDir",
  725.                 fileGetDemoDirectory());
  726.                 }
  727.                 return dragDirectory;
  728.                 break;
  729.         case DropDirectory:
  730.                 if (dropDirectory == NULL) {
  731.                         dropDirectory = (char *) XtMalloc(MAXPATHLEN + 1);
  732.                         sprintf(dropDirectory, "%s/FileDropDir",
  733.                 fileGetDemoDirectory());
  734.                 }
  735.                 return dropDirectory;
  736.                 break;
  737.         default:
  738.                 return NULL;
  739.         }
  740. }
  741.  
  742. /*
  743.  * fileStoreBuffer
  744.  *
  745.  * Store a buffer into a file in the drop directory.
  746.  * A temporary file may be created if required.
  747.  */
  748. char *
  749. fileStoreBuffer(
  750.     char        *name,
  751.     void        *buf,
  752.     int         len)
  753. {
  754.         char            path[MAXPATHLEN];
  755.     char        *dir = fileGetDirectoryName(DropDirectory);
  756.     struct stat    statInfo;
  757.         FILE            *fp;
  758.  
  759.     if (name == NULL)
  760.         name = "unnamed";
  761.  
  762.         sprintf(path, "%s/%s", dir, name);
  763.  
  764.     if (stat(path, &statInfo) == 0) {
  765.         char    *tPath;
  766.         
  767.         if ((tPath = tempnam(dir, name)) == NULL)
  768.             return (char *)NULL;
  769.         strcpy(path, tPath);
  770.         free(tPath);
  771.     }
  772.  
  773.         if ((fp = fopen(path, "w")) == NULL) {
  774.                 printf("Cannot create file \"%s\"\n", path);
  775.         return (char *)NULL;
  776.         }
  777.  
  778.         if (fwrite(buf, len, 1, fp) != 1) {
  779.                 printf("Cannot write to file \"%s\".\n", path);
  780.         return (char *)NULL;
  781.         }
  782.  
  783.         fclose(fp);
  784.  
  785.     return XtNewString(path);
  786. }
  787.